import { useEffect } from "react";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import * as CANNON from "cannon-es";

import { CannonEsDebuggerPro } from "@vladkrutenyuk/cannon-es-debugger-pro";

function App() {
    useEffect(() => {
        // 创建世界
        const scene = new THREE.Scene();
        // 创建相机
        const camera = new THREE.PerspectiveCamera(
            75,
            window.innerWidth / window.innerHeight,
            0.1,
            1000
        );
        // 设置相机位置
        camera.position.z = 10;
        camera.position.x = 0;
        camera.position.y = 10;

        const root = new THREE.Group();
        scene.add(root); // 将根节点添加到场景中

        // 创建两个数组更新物理世界和threejs世界
        const cannonBodies = [];
        const threeObjects = [];

        // 创建物理世界
        const world = new CANNON.World();
        // 允许休眠
        world.allowSleep = true;

        const color = 0xe60c0c; // or 'rgb(228, 14, 88)', '#e60c0c', 'red'
        const offset = 0.009;
        const cannonDebugger = new CannonEsDebuggerPro(root, world, color, offset);


        {
            // 设置重力
            world.gravity.set(0, -9.82, 0); // m/s²

            // 添加物理材质
            const boxMaterial = new CANNON.Material("boxMaterial"); // 创建材质
            boxMaterial.friction = 0; // 摩擦力
            // boxMaterial.restitution = 0.9; // 弹性

            // 添加光滑物理材质
            const boxSlipperyMaterial = new CANNON.Material("boxSlipperyMaterial");
            boxSlipperyMaterial.friction = 0; // 摩擦力

            // 添加弹性物理材质
            const boxElasticityMaterial = new CANNON.Material(
                "boxElasticityMaterial"
            );
            boxElasticityMaterial.friction = 0; // 摩擦力
            boxElasticityMaterial.restitution = 0.9; // 弹性

            {
                // 创建十个球
                const sphereShape = new CANNON.Sphere(0.5); // 创建球体形状
                let afterBody = null; // 记录上一个物体
                for (let i = 5; i > 0; i--) {
                    const body = new CANNON.Body({
                        shape: sphereShape, // 物体形状
                        mass: i == 5 ? 0 : 1, // 质量
                        position: new CANNON.Vec3(0, i * 1.2 + 6, 0), // 初始位置
                    })
                    world.addBody(body); // 添加到物理世界
                    cannonBodies.push(body); // 添加到物理数组中

                    // 创建threejs物体
                    const sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32); // 创建球体几何体
                    const sphereMaterial = new THREE.MeshBasicMaterial({
                        color: 0x00ff00, // 颜色
                    });
                    const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); // 创建球体网格
                    root.add(sphere); // 将球体添加到场景中
                    threeObjects.push(sphere); // 添加到threejs数组中


                    {
                        if (afterBody) {
                            // 创建距离约束
                            const constraint = new CANNON.DistanceConstraint(afterBody, body, 1.2); // 创建约束
                            // 添加约束到物理世界
                            world.addConstraint(constraint);
                        }
                        afterBody = body; // 记录上一个物体
                    }
                }


            }

            {
                window.addEventListener("click", () => {
                    // 创建一个球体
                    const sphereShape = new CANNON.Sphere(0.5); // 创建球体形状
                    const body = new CANNON.Body({
                        mass: 1, // 质量
                        position: new CANNON.Vec3(-6, 10, 0), // 初始位置
                    });
                    body.addShape(sphereShape); // 添加形状
                    world.addBody(body); // 添加到物理世界
                    cannonBodies.push(body); // 添加到物理世界数组

                    body.applyImpulse(new CANNON.Vec3(50, 0, 0)); // 添加冲击力

                    // 创建three一个圆
                    const geometry = new THREE.SphereGeometry(0.5, 32, 32);
                    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
                    const model = new THREE.Mesh(geometry, material);
                    // 将模型添加到场景中
                    root.add(model); // 将模型添加到根节点中
                    threeObjects.push(model); // 添加到threejs数组中

                })
            }

            {
                window.world = world
                console.log(world)
                world.addEventListener('postStep', () => {
                    for (let i = world.constraints.length - 1; i >= 0; i--) {
                        const constraint = world.constraints[i];
                        let multiplier = Math.abs(constraint.equations[0].multiplier);
                        if (multiplier > 2000) {
                            // 删除约束
                            world.removeConstraint(constraint);
                        }
                    }
                })
            }

            // 添加地面
            {
                // 创建平面
                const planeShape = new CANNON.Plane();
                const planeBody = new CANNON.Body({
                    mass: 0, // 质量为0表示静止物体
                    position: new CANNON.Vec3(0, -0.5, 0), // 初始位置
                    material: boxMaterial, // 使用摩擦力材质
                });
                // 设置平面的旋转
                planeBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0); // 绕x轴旋转90度
                planeBody.addShape(planeShape);
                world.addBody(planeBody);
            }
        }

        {
            {
            }

            {
                // 创建平面
                const planeShape = new THREE.BoxGeometry(10, 0.1, 10);
                const planeMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff });
                const plane = new THREE.Mesh(planeShape, planeMaterial);
                // 设置平面位置
                plane.position.y = -0.5;
                // 将平面添加到场景中
                scene.add(plane);
            }
        }

        // 创建渲染器
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 将渲染器添加到DOM中
        document.getElementById("app").appendChild(renderer.domElement);

        // 添加轨道控制器
        const controls = new OrbitControls(camera, renderer.domElement);
        controls.target.set(0, 5, 0); // 设置轨道控制器的目标点

        // 创建动画函数
        const animate = function () {
            // 更新物理世界
            world.step(1 / 60); // 60fps
            // 更新threejs世界
            for (let i = 0; i < cannonBodies.length; i++) {
                const body = cannonBodies[i];
                const mesh = threeObjects[i];
                // 更新threejs物体的位置和旋转
                mesh.position.copy(body.position);
                mesh.quaternion.copy(body.quaternion);
            }
            cannonDebugger.update(); // 更新调试器

            // 更新轨道控制器
            controls.update();

            requestAnimationFrame(animate);

            // 渲染场景
            renderer.render(scene, camera);
        };
        // 调用动画函数
        animate();

        return () => {
            // 清除渲染器
            renderer.dispose();
            // 清除场景
            scene.clear();
            // 清除相机
            camera.clear();
            // 清除渲染器DOM
            const app = document.getElementById("app");
            if (app) {
                app.removeChild(renderer.domElement);
            }
        };
    }, []);
    return <div id="app"></div>;
}

export default App;
